package com.igrid.demo.client;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public  class IGridHeader extends SimplePanel implements ResizeHandler,DragAndDropHandler{
	//Class properties
	private static final String STYLE_GRID_HEADER="gridHeader";
	
	//Private properties
	private FlexTable innerTable;
	
	//Columns List
	private List<HeaderCell> columns;
	
	//Column indicator
	private ColumnMoveIndicator indicator;

	
	public IGridHeader() {
		this.innerTable = new FlexTable();
		this.indicator=new ColumnMoveIndicator();
		this.columns=new ArrayList<HeaderCell>();
		initHeader();
		add(innerTable);
		build();
		setStyleName(STYLE_GRID_HEADER);
	}
	
	// Interface ResizeHandler
	public void onResize(Widget sender, Event event,int offSetX) {
		assert sender instanceof HeaderCell : "sender must be an instance of HeaderCell";
		HeaderCell target=(HeaderCell)sender;
		//Calculate the offset
		
		int targetWidth=target.getOffsetWidth()-offSetX;
		//reset the width of the table
		innerTable.setWidth(innerTable.getOffsetWidth()-offSetX+"px");
		//reset the width of the TD element
		Element tdElement=DOM.getParent(target.getElement());
		DOM.setStyleAttribute(tdElement, "width", targetWidth+"px");
		//reset the width of the HeaderCell element
		DOM.setStyleAttribute(target.getElement(), "width", targetWidth+"px");
	}
	// Interface DragAndDropHandler
	public void onDrag(Widget sender, Event event, int offSetX) {
		assert sender instanceof HeaderCell : "sender must be an instance of HeaderCell";
		HeaderCell targetCell = getTargetColumn(event);
		//In case of any NPE 
		if(targetCell==null) return;
		Element td=DOM.getParent(targetCell.getElement());
		this.indicator.setPosition(td.getAbsoluteLeft(),td.getAbsoluteTop(),td.getOffsetHeight());
	}

	

	public void onDrop(Widget sender, Event event, int offSetX) {
		assert sender instanceof HeaderCell : "sender must be an instance of HeaderCell";
		HeaderCell target=(HeaderCell)sender;	
		HeaderCell targetCell = getTargetColumn(event);
		//If the target cell is the original cell ,then nothing change
		this.indicator.hide();
		if(target==targetCell) return;
		Element from=DOM.getParent(target.getElement());
		Element to=DOM.getParent(targetCell.getElement());
		Element tr=DOM.getParent(from);
		tr.removeChild(from);
		tr.insertBefore(from,to);
	}	


	/**
	 * Add one widget to the header
	 * 
	 * @param cell
	 * @param columnIdx
	 */
	public void addColumn(HeaderCell cell){
		if(columns==null){
			columns=new ArrayList<HeaderCell>();
		}
		columns.add(cell);
	}
	
	/**
	 * Add one widget to the column at the given columnIdx
	 * 
	 * @param cell
	 * @param columnIdx
	 */
	public void addColumn(HeaderCell cell,int columnIdx){
		if(columns==null){
			columns=new ArrayList<HeaderCell>();
		}
		columns.add(columnIdx,cell);
	}
	
	/**
	 * Remove one column form the header
	 * 
	 * @param columnIdx
	 * @return
	 */
	public boolean removeColumn(int columnIdx) {
		try {
			this.columns.remove(columnIdx);
			return true;
		} catch (IndexOutOfBoundsException e) {
			return false;
		}
	}
	
	/**
	 * find the cellIndex of the header
	 * 
	 * @param cell
	 * @return -1 if not found
	 */
	public int getColumnIndex(HeaderCell cell){
		for(int i=0;i<columns.size();i++){
			if(cell==columns.get(i)){
				return i;
			}
		}
		return -1;
	}
	
	/**
	 * Refresh the header
	 * 
	 */
	public void build() {
		innerTable.clear();
		for (int i = 0; i < columns.size(); i++) {
			innerTable.setWidget(0, i, columns.get(i));
		}
	}
	
	/**
	 * Get the header scroll left value
	 * 
	 * @return
	 */
	public int getTotalScrollLeft(){
		return getTotalScrollLeft(this.getElement());
	}
	
	// Private Methods
	private void initHeader() {
		addColumn(new HeaderCell("Name", "center", this));
		addColumn(new HeaderCell("Id", "center", this));
		addColumn(new HeaderCell("Password", "center", this));
		addColumn(new HeaderCell("Address", "center", this));
	}

	private native int getTotalScrollLeft(Element elem) /*-{
		var scrollLeft = 0; 
		while (elem) {
		 scrollLeft += elem.scrollLeft;
		 elem = elem.offsetParent;
		}
		return scrollLeft;
	}-*/;

	private HeaderCell getTargetColumn(Event event) {
		int clientX = event.getClientX() + this.getTotalScrollLeft();
		HeaderCell targetCell = null;
		for (HeaderCell cell : columns) {
			int cell_left = cell.getAbsoluteLeft();
			int cell_right = cell.getAbsoluteLeft() + cell.getOffsetWidth();
			if (cell_left <= clientX && clientX <= cell_right) {
				targetCell = cell;
				break;
			}
		}
		return targetCell;
	}

}
